package tjs.study.notes.dotest.proxy.javassist.premain;

import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import sun.management.VMManagement;
import tjs.study.notes.dotest.TjsStudyNotesApplication;
import tjs.study.notes.dotest.proxy.service.UserService;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class DoTestPremain {

    /**
     * 启动方式1：
     * MANIFEST.MF配置Premain-Class
     * 实现方法PremainTransformer.premain(java.lang.String, java.lang.instrument.Instrumentation)
     * 启动时加上：-javaagent:/Users/piangpiang/Documents/my-workspace/my-mayun/tjs-study-notes-test2/tjs-study-notes/tjs-study-notes/tjs-study-dotest/src/main/java/tjs/study/notes/dotest/proxy/javassist/premain/PremainTraTest.jar
     * Javassist
     *
     * 启动方式2：
     * MANIFEST.MF配置Agent-Class
     * 实现方法PremainTransformer.agentmain(java.lang.String, java.lang.instrument.Instrumentation)
     * 类被首次加载前，执行virtualMachine.loadAgent
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
//        int jvmPID = jvmPid();
//        System.out.println("jvmPID: " + jvmPID);
//        loadAgent(jvmPID);

        UserService userService = new UserService("test");
        userService.login();
        userService.logout();//static final修饰的方法也能被代理

        // 这里直接通过java反射调用
        userService.invokeGetUserName();
    }

    private static void loadAgent(int jvmPID) throws AttachNotSupportedException, IOException, AgentLoadException, AgentInitializationException {
        VirtualMachine virtualMachine = VirtualMachine.attach(String.valueOf(jvmPID));
        virtualMachine.loadAgent(TjsStudyNotesApplication.work_space + "/proxy/javassist/premain/PremainTraTest.jar");
    }

    public static final int jvmPid() {
        try {
            RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
            Field jvm = runtime.getClass().getDeclaredField("jvm");
            jvm.setAccessible(true);
            VMManagement mgmt = (VMManagement) jvm.get(runtime);
            Method pidMethod = mgmt.getClass().getDeclaredMethod("getProcessId");
            pidMethod.setAccessible(true);
            int pid = (Integer) pidMethod.invoke(mgmt);
            return pid;
        } catch (Exception e) {
            return -1;
        }
    }
}